package me.firstapp.repository.shop.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import me.firstapp.common.utils.DateUtils;
import me.firstapp.common.utils.Page;
import me.firstapp.common.utils.StrUtils;
import me.firstapp.module.shop.Order;
import me.firstapp.repository.base.BaseRepository;
import me.firstapp.repository.base.impl.EntityRepositoryImpl;
import me.firstapp.repository.shop.OrderRepository;

@Repository
public class OrderRepositoryImpl extends EntityRepositoryImpl<Order> implements OrderRepository {
	
	@Autowired
	protected BaseRepository baseRepository;

	@Override
	protected Class<Order> getPersistentClass() {
		return Order.class;
	}

	@Override
	public Order findOrderByOrderNo(String orderNo, Long apiClientId) {
		StringBuilder sql = new StringBuilder(" FROM Order bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.apiClientId =:apiClientId ");
		parameters.put("apiClientId", apiClientId);

		sql.append(" AND bean.orderNo=:orderNo ");
		parameters.put("orderNo", orderNo);

		List<Order> results = super.query(Order.class, sql.toString(), parameters);
		return results.isEmpty() ? null : results.get(0);
	}

	@Override
	public Order findOrderByMemberIdAndOrderNo(Long memberId, String orderNo, Long apiClientId) {
		StringBuilder sql = new StringBuilder(" FROM Order bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND bean.apiClientId =:apiClientId ");
		parameters.put("apiClientId", apiClientId);

		sql.append(" AND bean.member.id=:memberId ");
		parameters.put("memberId", memberId);

		sql.append(" AND bean.orderNo=:orderNo ");
		parameters.put("orderNo", orderNo);

		List<Order> results = super.query(Order.class, sql.toString(), parameters);
		return results.isEmpty() ? null : results.get(0);
	}

	@Override
	public Page<Order> findOrderPage(Integer pageNo, Integer pageSize, Long memberId, Integer status,
			Long apiClientId) {
		StringBuilder sql = new StringBuilder(" FROM Order bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		if (memberId != null) {
			sql.append(" AND bean.member.id=:memberId ");
			parameters.put("memberId", memberId);
		}

		if (status != null) {
			if (status != 0) {
				sql.append(" AND bean.status=:status ");
				parameters.put("status", status);
			} else {// 未支付和已取消的订单要一起查询
				sql.append(" AND bean.status IN(0,4) ");
			}
		}

		sql.append(" AND bean.apiClientId =:apiClientId ");
		parameters.put("apiClientId", apiClientId);

		sql.append(" ORDER BY bean.createTime DESC");

		return super.queryForPage(Order.class, sql.toString(), parameters, pageNo, pageSize);
	}

	@Override
	public Page<Order> findOrderPage(Integer pageNo, Integer pageSize, Map<String, Object> searchParams,
			String sortParam, String sortType, Date startTime, Date endTime, Long apiClientId) {
		StringBuilder sql = new StringBuilder(" FROM Order bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<String, Object>();

		if (searchParams != null) {
			Set<String> keys = searchParams.keySet();
			for (String key : keys) {
				Object value = searchParams.get(key);
				if (value != null) {
					if ("status".equals(key)) {
						String _value = (String) value;
						Integer status = Integer.valueOf(_value);
						sql.append(" AND bean.status =:status ");
						parameters.put("status", status);
					} else {
						sql.append(" AND bean." + key + " LIKE :value ");
						parameters.put("value", "%" + value + "%");
					}
				}
			}
		}
		Date _startTime = null;
		if (startTime != null) {
			String startTimeStr = DateUtils.getDateStr(startTime, "yyyy-MM-dd") + " 00:00:00";
			_startTime = DateUtils.getDateFromDateStr(startTimeStr, "yyyy-MM-dd HH:mm:ss");

		}
		Date _endTime = null;
		if (endTime != null) {
			String endTimeStr = DateUtils.getDateStr(endTime, "yyyy-MM-dd") + " 23:59:59";
			_endTime = DateUtils.getDateFromDateStr(endTimeStr, "yyyy-MM-dd HH:mm:ss");
		}

		if (_startTime != null) {
			sql.append(" AND bean.createTime >=:startTime ");
			parameters.put("startTime", _startTime);
		}
		if (_endTime != null) {
			sql.append(" AND bean.createTime <=:endTime");
			parameters.put("endTime", _endTime);
		}

		sql.append(" AND bean.apiClientId =:apiClientId ");
		parameters.put("apiClientId", apiClientId);

		if (StrUtils.isNotNULL(sortParam) && StrUtils.isNotNULL(sortType)) {
			sql.append(" ORDER BY " + sortParam + " " + sortType);
		}

		return super.queryForPage(Order.class, sql.toString(), parameters, pageNo, pageSize);
	}

	@Override
	public List<Order> findOrders(Long memberId, Integer status, Long apiClientId) {
		StringBuilder sql = new StringBuilder(" FROM Order bean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		if (memberId != null) {
			sql.append(" AND bean.member.id=:memberId ");
			parameters.put("memberId", memberId);
		}

		if (status != null) {
			sql.append(" AND bean.status=:status ");
			parameters.put("status", status);
		}

		sql.append(" AND bean.apiClientId =:apiClientId ");
		parameters.put("apiClientId", apiClientId);

		sql.append(" ORDER BY bean.createTime DESC");
		return super.query(Order.class, sql.toString(), parameters);
	}

	@Override
	public Long findPayedOrderCountsByPayTime(Date startTime, Date endTime, Long apiClientId) {
		StringBuilder sql = new StringBuilder(
				"SELECT COUNT(orderBean.id) FROM Order orderBean, PayRecord payRecordBean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND orderBean.orderNo = payRecordBean.orderNo ");
		sql.append(" AND orderBean.apiClientId = payRecordBean.apiClientId ");
		sql.append(" AND orderBean.apiClientId =:apiClientId ");
		parameters.put("apiClientId", apiClientId);

		Date _startTime = null;
		if (startTime != null) {
			String startTimeStr = DateUtils.getDateStr(startTime, "yyyy-MM-dd") + " 00:00:00";
			_startTime = DateUtils.getDateFromDateStr(startTimeStr, "yyyy-MM-dd HH:mm:ss");

		}
		Date _endTime = null;
		if (endTime != null) {
			String endTimeStr = DateUtils.getDateStr(endTime, "yyyy-MM-dd") + " 23:59:59";
			_endTime = DateUtils.getDateFromDateStr(endTimeStr, "yyyy-MM-dd HH:mm:ss");
		}

		if (startTime != null && endTime != null) {
			sql.append(" AND payRecordBean.payTime >=:startTime ");
			parameters.put("startTime", _startTime);
			sql.append(" AND payRecordBean.payTime <=:endTime ");
			parameters.put("endTime", _endTime);
		} else if (startTime != null && endTime == null) {
			sql.append(" AND payRecordBean.payTime >=:startTime ");
			parameters.put("startTime", _startTime);
		} else if (startTime == null && endTime != null) {
			sql.append(" AND payRecordBean.payTime <=:endTime ");
			parameters.put("endTime", _endTime);
		}
		sql.append(" AND payRecordBean.status = 1 ");

		List<Long> result = super.query(Long.class, sql.toString(), parameters);
		return result.isEmpty() ? 0 : result.get(0);
	}

	@Override
	public Double findPayedOrderPointsByPayTime(Date startTime, Date endTime, Long apiClientId) {
		StringBuilder sql = new StringBuilder(
				"SELECT SUM(payRecordBean.payValue) FROM Order orderBean, PayRecord payRecordBean WHERE 1=1 ");
		Map<String, Object> parameters = new HashMap<>();

		sql.append(" AND orderBean.orderNo = payRecordBean.orderNo ");
		sql.append(" AND orderBean.apiClientId = payRecordBean.apiClientId ");
		sql.append(" AND orderBean.apiClientId =:apiClientId ");
		parameters.put("apiClientId", apiClientId);

		Date _startTime = null;
		if (startTime != null) {
			String startTimeStr = DateUtils.getDateStr(startTime, "yyyy-MM-dd") + " 00:00:00";
			_startTime = DateUtils.getDateFromDateStr(startTimeStr, "yyyy-MM-dd HH:mm:ss");

		}
		Date _endTime = null;
		if (endTime != null) {
			String endTimeStr = DateUtils.getDateStr(endTime, "yyyy-MM-dd") + " 23:59:59";
			_endTime = DateUtils.getDateFromDateStr(endTimeStr, "yyyy-MM-dd HH:mm:ss");
		}

		if (startTime != null && endTime != null) {
			sql.append(" AND payRecordBean.payTime >=:startTime ");
			parameters.put("startTime", _startTime);
			sql.append(" AND payRecordBean.payTime <=:endTime ");
			parameters.put("endTime", _endTime);
		} else if (startTime != null && endTime == null) {
			sql.append(" AND payRecordBean.payTime >=:startTime ");
			parameters.put("startTime", _startTime);
		} else if (startTime == null && endTime != null) {
			sql.append(" AND payRecordBean.payTime <=:endTime ");
			parameters.put("endTime", _endTime);
		}
		sql.append(" AND payRecordBean.status = 1 ");
		sql.append(" AND orderBean.status = 1 ");

		return baseRepository.queryForDouble(sql.toString(), parameters);
	}

}
